(ns ru.nsu.fit.g7202.seml.sepath-test
  (:use clojure.test
        ru.nsu.fit.g7202.test.assert)
  (:require [ru.nsu.fit.g7202.seml :as seml]
            [ru.nsu.fit.g7202.seml.sepath :as sepath]))


(def obj '{people [{firstName "Иван",
                    lastName "Иванов",
                    addrs [{streetAddress "Пирогова, 2",
                            city "Новосибирск",
                            postalCode 630090} 
                           {city "Краснообск", 
                            postalCode 630501}], 
                    phoneNumbers ["812 123-1234"
                                  "916 123-4567"]} 
                   {firstName "Пётр",
                    lastName "Петров", 
                    addrs [{streetAddress "Ленина, 1",
                            city "Москва",
                            postalCode 124365}], 
                    phoneNumbers []}]
           animals [{firstName "Кошка"
                     addrs [{streetAddress "Пирогова, 2",
                             city "Новосибирск",
                             postalCode 630090}]}]} ) 


(deftest select-test-filter
  (let []
    (assert-eq
      ["Пётр"]
      (sepath/select obj '(people * [(lastName) = "Петров"] firstName) ))
    (assert-eq
      ["Иван", "Пётр"]
      (sepath/select obj '(people * [0 < (addrs :count)] firstName) ))
    (assert-eq
      ["Иван"]
      (sepath/select obj '(people * [(addrs :count) > 0 and (phoneNumbers :count) > 0] firstName) ))
    (assert-eq
      ["Иван", "Пётр"]
      (sepath/select obj '(people * [(addrs :count) > 0 or (phoneNumbers :count) > 0] firstName) ))
    (assert-eq
      ["Иван"]
      (sepath/select obj '(people * [(addrs :count) + (phoneNumbers :count) >= 2] firstName) ))
    (assert-eq
      ["Пётр"]
      (sepath/select obj '(people * [(addrs :count) mul (phoneNumbers :count) = 0] firstName) ))
  ))

(deftest select-test-subexpr
  (let []
    (assert-eq
      ["Иван" "Иванов" "Новосибирск"]
      (sepath/select obj '(people 0 (firstName | lastName | addrs 0 city)) ))
    (assert-eq
      ["Новосибирск" "Иван" "Иванов"]
      (sepath/select obj '(people 0 (addrs 0 city | firstName | lastName)) ))
    (assert-eq
      ["Иван" "Новосибирск" "Иванов"]
      (sepath/select obj '(people 0 (firstName | addrs 0 city | lastName)) ))
    (assert-eq
      '[{streetAddress "Пирогова, 2", city "Новосибирск", postalCode 630090} {city "Краснообск", postalCode 630501} "812 123-1234" "916 123-4567"]
      (sepath/select obj '(people 0 (addrs | phoneNumbers) *) ))
  ))

(deftest select-test-star
  (let []
    (assert-eq
      ["Новосибирск", "Москва"]
      (sepath/select obj '(people * addrs 0 city)))
    (assert-eq
      ["Новосибирск", "Краснообск", "Москва"]
      (sepath/select obj '(people * addrs * city)))
    (assert-eq
      ["Краснообск", "Москва"]
      (sepath/select obj '(people * addrs :last city)))
    (assert-eq
      [2, 1]
      (sepath/select obj '(people * addrs :count)))
  ))

(deftest select-test-double-star
  (let []
    (assert-eq
      ["Иван", "Пётр", "Кошка"]
      (sepath/select obj '(** firstName)))
  ))


(deftest select1-test
   (let [
         filename "Data/input.seml"
         obj (seml/parseFile filename)
         #_'{people [{
                     firstName "Иван",
                     lastName "Иванов",
                     addrs [{streetAddress "Пирогова, 2",
                             city "Новосибирск",
                             postalCode 630090} 
                            {city "Краснобск", 
                             postalCode 630501}], 
                     phoneNumbers ["812 123-1234"
                                   "916 123-4567"]} 
                    {firstName "Пётр",
                     lastName "Петров", 
                     addrs [{streetAddress "Ленина, 1",
                             city "Москва",
                             postalCode 124365}], 
                     phoneNumbers []}]}
        ]
     (assert-eq "Иван" (sepath/select1 obj '(people 0 firstName)))
     (assert-eq "Иванов" (sepath/select1 obj '(people 0 lastName)))
     (assert-eq "Пирогова, 2" (sepath/select1 obj '(people 0 addrs 0 streetAddress)))
     (assert-eq "Новосибирск" (sepath/select1 obj '(people 0 addrs 0 city)))
     (assert-eq 630090 (sepath/select1 obj '(people 0 addrs 0 postalCode)))
     (assert-eq "Пирогова, 3" (sepath/select1 obj '(people 0 addrs 1 streetAddress)))
     (assert-eq "Новосибирск" (sepath/select1 obj '(people 0 addrs 1 city)))
     (assert-eq 630090 (sepath/select1 obj '(people 0 addrs 1 postalCode)))
     (assert-eq "812 123-1234" (sepath/select1 obj '(people 0 phoneNumbers 0)))
     (assert-eq "916 123-4567" (sepath/select1 obj '(people 0 phoneNumbers 1)))
     
     (assert-eq "Пётр" (sepath/select1 obj '(people 1 firstName)))
     (assert-eq "Петров" (sepath/select1 obj '(people 1 lastName)))
     (assert-eq [] (sepath/select1 obj '(people 1 addrs)))
     (assert-eq [] (sepath/select1 obj '(people 1 phoneNumbers)))
   ))
